require 'gtksourceview'
require 'stringio'

module Sph
  module ObjectBrowser
    class EvalView < Gtk::VPaned
      def initialize
        super
        set_size_request(200, 150)
        
        font = Pango::FontDescription.new("verdana 12")
        lm = Gtk::SourceLanguagesManager.new
        lang = lm.available_languages.find {|x| x.name == "Ruby"}
        @sourceView = Gtk::SourceView.new(Gtk::SourceBuffer.new(lang))
        @sourceView.buffer.highlight = true
        @sourceView.pixels_above_lines = 2
        @sourceView.modify_font(font)
        @sourceView.auto_indent = true
        @sourceView.show_line_numbers = true
        @outputView = Gtk::TextView.new
        @outputView.editable = false
        @outputView.cursor_visible = false
        @outputView.modify_font(font)

        frame = Gtk::Frame.new; frame.child = Sph::scroller(@outputView)
        pack1(frame, true, false)

        frame = Gtk::Frame.new; frame.child = Sph::scroller(@sourceView)
        frame.child.set_height_request(16) # 3 lines
        pack2(frame, true, false)
        
        @binding = nil
        
        @sourceView.signal_connect("key-press-event") do |w, e|
          cleanEvent = Sph::processKeyEvent(e)
          if cleanEvent[:key] == ?r and cleanEvent[:ctrl]
            evaluate
            true
          end
        end
        @reset = true
      end
      
      def print(text)
        @outputView.buffer.text += text
      end
      
      def setSubject(object, name)
        @subject = {:object => object, :name => name}
      end
      
      def evaluate
        @outputView.buffer.text = "" if @reset
        if @subject
          print "Evaluating under #{@subject[:name]}: "
          print "#{@subject[:object].inspect}\n\n"
        else
          print "Evaluating in secret context\n\n"
        end
        code = @sourceView.buffer.text
        $stdout = StringIO.new
        begin
          if @subject
            result = @subject[:object].instance_eval(code)
          else
            result = eval(code)
          end
        rescue Exception
          print "Evaluation error: #{$!}\n"
        ensure
          print $stdout.string
          print "\n=> #{result ? result : "nil"}"
          $stdout = STDOUT
        end
      end
    end #class EvalView
  end #module ObjectBrowser
end #module Sph